﻿using mozhi.smarterp.Finance.Accounts.Repository;
using mozhi.smarterp.Finance.Accounts.Services;
using mozhi.smarterp.Finance.Querys;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Mozhi.Abp.Core.Extensions;
using Volo.Abp.Guids;
using mozhi.smarterp.Finance.Basedatas.Services;
using mozhi.smarterp.Finance.Basedatas;
using mozhi.smarterp.Finance.Banks.Repository;
using mozhi.smarterp.Finance.Finances.Services;
using mozhi.smarterp.Finance.Finances.ValueObjects;
using mozhi.smarterp.Finance.Finances.Repository;
using Mozhi.Abp.Domain.BasicData.Repositories;
using Mozhi.Abp.Domain.BasicData;

namespace mozhi.smarterp.Finance.Accounts
{
    public class AccountBalanceAppService : FinanceAppService, IAccountBalanceAppService
    {
        private IAccountBalanceRepository _repository;
        private IAccountRepository _accountRepository;
        private AccountBalanceManager _manager;
        private IOrganizationRepository _currentOrganization;
        private IGuidGenerator _guidGenerator;
        private ICurrencyRepository _currencyRepository;
        private DimensionGroupValueManager _dimensionGroupValueManager;
        private IBankAccountRepository _bankAccountRepository;
        private SettlementMananger _settlementMananger;
        private ISettlementRepository _settlementRepository;
        public AccountBalanceAppService(IAccountBalanceRepository repository, AccountBalanceManager manager,
            IAccountRepository accountRepository, IOrganizationRepository currentOrganization, ICurrencyRepository currencyRepository,
            IGuidGenerator guidGenerator , DimensionGroupValueManager dimensionGroupValueManager , IBankAccountRepository bankAccountRepository
            , SettlementMananger settlementMananger , ISettlementRepository settlementRepository)
        {
            _repository = repository;
            _manager = manager;
            _accountRepository = accountRepository;
            _currentOrganization = currentOrganization;
            _guidGenerator = guidGenerator;
            _currencyRepository = currencyRepository;
            _dimensionGroupValueManager = dimensionGroupValueManager;
            _currencyRepository = currencyRepository;
            _bankAccountRepository = bankAccountRepository;
            _settlementMananger = settlementMananger;
            _settlementRepository = settlementRepository;
        }

        public async Task<List<AccountBalanceDto>> FindAsync(AccountBalanceQuery query)
        {
            //var result = new List<AccountBalanceDto>();

            //if (query.IsInitalize)
            //{
            //    //query.Period = _currentOrganization.ActivatedDate.Value.ToPeriod().ToPrePeriod();
            //    query.StartPeriod = null;
            //    query.EndPeriod = null;
            //}

            //var balances = await _repository.FindAsync(new AccountBalanceQuery() { Keyword = query.Keyword, AccountIds = query.AccountIds, Period = query.Period, IncludeDimension = query.IncludeDimension });

            //var currencyIds = balances.Where(x => x.CurrencyId.HasValue).Select(x => x.CurrencyId.Value).Distinct().ToList();

            //var currenys = new List<Currency>(); // await _currencyRepository.FindAsync(new PageQuery() { Ids = currencyIds, PageIndex = 1, PageSize = int.MaxValue });

            //var dimensionGroupValueIds = balances.Where(x => x.DimensionGroupValueId.HasValue).Select(x => x.DimensionGroupValueId.Value).Distinct().ToList();

            //var dimensionGroupValues = await _dimensionGroupValueManager.GetDimensionGroupValues(dimensionGroupValueIds);

            //var accountIds = balances.Select(x => x.AccountId).Distinct().ToList();

            //var accounts = await _accountRepository.FindAsync(new AccountQuery() { Ids = query.AllAccount == true ? null : accountIds });

            //foreach (var account in accounts)
            //{
            //    var matchBalances = balances.Where(x => x.AccountId == account.Id).ToList();

            //    var data = new AccountBalanceDto() { Items = new List<AccountBalanceItemDto>() };

            //    data.Id = account.Id;
            //    data.AccountId = account.Id;
            //    data.AccountCode = account.Code;
            //    data.AccountName = account.Name;
            //    data.ParentId = account.ParentId;

            //    foreach (var balance in matchBalances)
            //    {
            //        var itemDto = ObjectMapper.Map<AccountBalance, AccountBalanceItemDto>(balance);
            //        itemDto.CurrencyCode = currenys.FirstOrDefault(x => x.Id == balance.CurrencyId)?.Code;

            //        var matchDimensionGroupValue = dimensionGroupValues.FirstOrDefault(x => x.Id == balance.DimensionGroupValueId);

            //        if (matchDimensionGroupValue != null && matchDimensionGroupValue.Items != null)
            //            itemDto.DimensionGroupValueItems = ObjectMapper.Map<List<DimensionGroupValueItem>, List<DimensionGroupValueItemDto>>(matchDimensionGroupValue.Items);

            //        data.Items.Add(itemDto);
            //    }

            //    result.Add(data);
            //}
            //return result;
            throw new NotImplementedException();
        }

        public async Task<AccountBalanceDto> GetAsync(Guid id)
        {
            var balance = await _repository.GetAsync(id);

            if (balance == null)
                throw new UserFriendlyException("科目余额不存在", "100000");

            return ObjectMapper.Map<AccountBalance , AccountBalanceDto>(balance);
        }

       
        public async Task<AccountBalanceDto> UpdateAsync(AccountBalanceUpdateDto dto)
        {
            //if (dto.Period == 0)
            //    throw new UserFriendlyException("需要指定期间","100000");

            //if (dto.Items == null || dto.Items.Count == 0)
            //    throw new UserFriendlyException("至少需要一条余额数据", "100000");

            //if (dto.Items.Exists(x => x.CurrencyId == default))
            //    throw new UserFriendlyException("科目余额币别不能为空", "100000");

            //await _manager.ValidateAccountAsync(dto.AccountId);

            //dto.Items = dto.Items.Where(x => x.CurrencyId != default).ToList();

            //var openingPeriod = (await GetOrganizationAsync()).ActivatedDate?.ToPeriod();

            //var minPeriod = openingPeriod.Value.ToPrePeriod();

            //dto.Period = dto.Period > minPeriod ? dto.Period : minPeriod;

            //dto.Items.ForEach(item =>
            //{
            //    item.Id = item.Id.HasValue ? item.Id : _guidGenerator.Create();
            //});

            ////查询科目整个树结点科目，用于后面计算父级科目余额
            //var accounts = await _accountRepository.GetAccountAndParentsAsync(dto.AccountId, false);

            //var rootAccount = accounts.FirstOrDefault(x => x.ParentId == null);

            //accounts = await _accountRepository.GetAccountChildrenAsync(rootAccount.Id, true);

            //accounts.Add(rootAccount);

            //var balances = await _repository.FindAsync(new AccountBalanceQuery() { AccountIds = accounts.Select(x => x.Id).ToList(), Period = dto.Period });

            //var account = accounts.FirstOrDefault(x => x.Id == dto.AccountId);


            //var bankAccountIds = accounts.Where(x => x.BankAccountId.HasValue).Select(x => x.BankAccountId.Value).ToList();

            //var bankAccounts = bankAccountIds.Count==0 ? new List<Banks.BankAccount>() : await _bankAccountRepository.FindAsync(new QueryBase() { Ids = bankAccountIds });

            //var processingBalances = new List<AccountBalance>();

            //foreach (var item in dto.Items)
            //{
            //    item.DimensionGroupValueItems = item.DimensionGroupValueItems == null ? null : item.DimensionGroupValueItems.Where(x => !x.Value.IsNullOrEmpty()).ToList();

            //    await _dimensionGroupValueManager.ValidateDimensionGroupValue(account.DimensionItems, GetDimensionGroupValueItems(item.DimensionGroupValueItems));
            //    //带核算维度，币别的余额
            //    var dimensionItemsQuery = ObjectMapper.Map<List<DimensionGroupValueItemDto>, List<DimensionGroupValueItemQuery>>(item.DimensionGroupValueItems);
            //    var dimensionGroupValueId = await _dimensionGroupValueManager.GetDimensionGroupValueId(new DimensionGroupValuePageQuery() { Items = dimensionItemsQuery, PageIndex = 1, PageSize = 1 });

            //    var id = !item.Id.HasValue ? _guidGenerator.Create() : item.Id.Value;

            //    var balance = new AccountBalance(id, dto.AccountId, item.CurrencyId, dto.Period, dimensionGroupValueId, account.Direction);
            //    balance.ChangeAmount(account.IsForeignCurrency, (await GetOrganizationAsync()).StandardCurrencyId.Value, null, item.OpeningAmount, item.OpeningAmountFr,
            //        item.CurrentYearDebitAmount, item.CurrentYearDebitAmountFr, item.CurrentYearCreditAmount, item.CurrentYearCreditAmountFr,
            //        item.DebitAmount, item.DebitAmountFr, item.CreditAmount, item.CreditAmountFr);
            //    processingBalances.Add(balance);
            //}

            //await _manager.UpdateAsync(dto.AccountId, processingBalances, balances, accounts, bankAccounts);

            //await _repository.InsertOrUpdateAsync(balances);

            //return ObjectMapper.Map<List<AccountBalance>, AccountBalanceDto>(processingBalances);
            throw new NotImplementedException();
        }

        public async Task<bool> DeleteAsync(Guid id)
        {
            //var balance = await _repository.FindAsync(id);

            //if (balance == null)
            //    throw new UserFriendlyException("科目余额不存在", "100000");

            //var accounts = await _accountRepository.GetAccountAndParentsAsync(balance.AccountId, false);

            //var rootAccount = accounts.FirstOrDefault(x => x.ParentId == null);

            //accounts = await _accountRepository.GetAccountChildrenAsync(rootAccount.Id, true);

            //accounts.Add(rootAccount);

            //var balances = await _repository.FindAsync(new AccountBalanceQuery() { AccountIds = accounts.Select(x => x.Id).ToList(), Period = balance.Period });

            //var baseCurrencyId = (await GetOrganizationAsync()).StandardCurrencyId;

            //await _manager.DeleteAsync(balance, balances, accounts, new List<Banks.BankAccount>(), baseCurrencyId.Value);

            //await _repository.InsertOrUpdateAsync(balances);

            //await _repository.DeleteAsync(balance);

            //return true;
            throw new NotImplementedException();
        }

        public async Task<bool> ClearAsync()
        {
            var period = await _settlementMananger.GetInitalizePeriodAsync();

            var settlementCount = await _settlementRepository.GetCountAsync(new SettlementQuery() { Period = period, Closed = true });

            if (settlementCount > 0)
                throw new UserFriendlyException("已完成初始化，不能删除科目余额", "100000");

            var balances = await _repository.FindAsync(new AccountBalanceQuery() { Period = period });

            if (balances.Count == 0)
                return true;

            await _repository.DeleteAsync(balances);

            return true;

        }

        public async Task<TrialBalanceResultDto> TrialBalance()
        {
            var result = await _settlementMananger.GetTrialBalanceAsync();

            return ObjectMapper.Map<TrialBalanceResult, TrialBalanceResultDto>(result);
        }

        public async Task<int> GetCountAsync(int? period)
        {
            var filter = new AccountBalanceQuery() { Period = period };

            var count = await _repository.GetCountAsync(filter);

            return count;
        }

        #region

        #endregion


    }
}
